package com.zkzl.cdz.handler;

import com.zkzl.cdz.util.Tools;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

@Slf4j
public class RequestDecoder extends ByteToMessageDecoder {

    //记录上次未读完的字节
    private ByteBuf tempMessage = Unpooled.buffer();//申请一块内存保存分包数据,根据最后一次0d出现的位置选择保留哪部分数据
    private int CurrentSize = 0; //本次新传输的字节数
    private int TempMessageSize = 0; //上次剩余的字节数
    private ByteBuf WorkByteBuf = Unpooled.buffer();//最终操作的ByteBuf
    private byte[] WorkPackBuf = null;//最终操作的字节数组

    /**
     * 用来进行解包操作，得到完整的合法数据包55 aa 为头 0d为尾
     *
     * @param channelHandlerContext
     * @param byteBuf
     * @param list
     * @throws Exception
     */
    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
        //log.info("=========开始分析数据========");
        WorkByteBuf.clear();
        CurrentSize = byteBuf.readableBytes();//当前流可读取字节数
        TempMessageSize = tempMessage.readableBytes();//上次保存的可读字节数
        //进行合包操作
        if (TempMessageSize == 0) {
            WorkPackBuf = new byte[CurrentSize];//ByteBuf的转换的字节数组
            WorkByteBuf.writeBytes(byteBuf);
            WorkByteBuf.readBytes(WorkPackBuf);
        } else if (TempMessageSize > 0) {
            WorkByteBuf.writeBytes(tempMessage);
            WorkByteBuf.writeBytes(byteBuf);
            WorkPackBuf = new byte[CurrentSize + TempMessageSize];
            WorkByteBuf.readBytes(WorkPackBuf);
        } else {
            tempMessage.clear();
        }
        //StringBuilder sb = new StringBuilder();
        /*for (byte aa : WorkPackBuf) {
            //sb.append(Integer.toHexString(Tools.ByteConvertIntHL(aa)) + "\t");
            System.out.println("获取数据： "+Integer.toHexString(Tools.ByteConvertIntHL(aa)) + "\t");
        }*/
        //log.info("获取包数据：" + sb.toString());
        // log.info("=========数据读取完毕========");
        if (WorkPackBuf != null) {
            List<Integer> head = new ArrayList<>();//保存开始位置下标
            List<Integer> end = new ArrayList<>();//保存结束位置下标
            int EndHead = 0;
            for (int index = 0; index < CurrentSize + TempMessageSize - 1; index++) {
                if (Tools.ByteConvertIntHL(WorkPackBuf[index]) == 0x55 & Tools.ByteConvertIntHL(WorkPackBuf[index + 1]) == 0xAA) {
                    head.add(index);
                    if (CurrentSize + TempMessageSize >= index + 4) {//如果读取的头位置后还有2个字节，则读取长度,判断0c出现的位置
                        byte[] endB = new byte[2];
                        System.arraycopy(WorkPackBuf, index + 2, endB, 0, 2);
                        int endIndex = index + 6 + Tools.ByteConvertIntHL(endB);
                        if (endIndex <= CurrentSize + TempMessageSize - 1) {
                            end.add(endIndex);
                        }
                    }
                }
            }
            for (Integer endInx : end) {
                EndHead = endInx;
                for (Integer headInx : head) {
                    if (headInx < EndHead & WorkPackBuf[endInx] == 0x0d) {
                        byte[] completePackage = new byte[endInx - headInx + 1];//创建一个完整的可解析数据包
                        StringBuilder sb1 = new StringBuilder();
//                        for (byte aa : completePackage) {
//                            sb1.append(Integer.toHexString(Tools.ByteConvertIntHL(aa)) + "\t");
//                        }
//
//                        log.info("解析后的数据: " + sb1.toString());
                        System.arraycopy(WorkPackBuf, headInx, completePackage, 0, endInx - headInx + 1);
                        list.add(completePackage);
                        break;
                    } else {
                        head.remove(headInx);
                    }
                }
                EndHead = endInx;//记录最后一次出现的0d位置
            }
            //将最后一个0d以后的数都存入临时缓存中,也可能没有0d， 那就全部保存
            if (EndHead == 0) {
                tempMessage.clear();
                WorkByteBuf.resetReaderIndex();
                if (WorkByteBuf.writableBytes() > CurrentSize + TempMessageSize) {
                    tempMessage.writeBytes(WorkByteBuf);
                }
            } else if (EndHead == CurrentSize + TempMessageSize - 1) {//如果最后一次出现的位置就是最后一个字符则只清空不添加
                tempMessage.clear();
            } else {
                tempMessage.clear();
                if (WorkByteBuf.writableBytes() > CurrentSize + TempMessageSize) {
                    tempMessage.writeBytes(WorkByteBuf, EndHead, CurrentSize + TempMessageSize - EndHead);
                }
                tempMessage.writeBytes(WorkByteBuf);
            }
        }
    }
}
